package com.zz;

import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.*;
import com.zz.util.CertUtil;
import com.zz.util.LocalFileUtil;
import org.apache.commons.io.IOUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;

/**
 * Hello world!
 *
 */
public class App 
{
    /**
     * PDF签名，数字签名签在pdf上面。
     * itextpdf5.5.0.jar，backport-util-concurrent-1.0.jar,bcpkix-jdk15on-1.52.jar,bcprov-jdk15on-1.52.jar
     */
    public static void signPDF(String pdfPath, String moulagePath) throws Exception
    {
        ByteArrayOutputStream faos = null;
        ByteArrayInputStream fbis = null;
        PdfReader reader = null;
        PdfStamper stamper = null;
        String certPath = "C:\\Users\\Administrator\\Desktop\\1.pfx";
        String password = "139739";
        try
        {
            byte [] certData = LocalFileUtil.localBufferRead(certPath);
            X509Certificate x509Cert = CertUtil.getCertificateByPfx(certData, password);
            Certificate[] certChain = new Certificate[1];
            certChain[0] = x509Cert;
            KeyStore ks = KeyStore.getInstance("pkcs12");
//            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            ks.load(new ByteArrayInputStream(certData), password.toCharArray()); //123456为私钥密码
            String alias = (String) ks.aliases().nextElement();
            PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password.toCharArray());

            faos = new ByteArrayOutputStream();
            //读取待签名pdf
            byte [] fileData = LocalFileUtil.localBufferRead(pdfPath);
            fbis = new ByteArrayInputStream(fileData);
            reader = new PdfReader(fbis);
            Rectangle rect = reader.getPageSize(1);
            float pdf_width = rect.getWidth();
            float pdf_height = rect.getHeight();
            stamper = PdfStamper.createSignature(reader, faos, '\0', null, true);
            PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
            Image image = Image.getInstance(moulagePath);
            appearance.setReason("");
            appearance.setLocation("");

//            appearance.setSignatureGraphic(image);
            appearance.setAcro6Layers(true);
            appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);
//            appearance.setImage(image);
//            appearance.setVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig");

//            appearance.setVisibleSignature(new Rectangle(
//                    (float) (sealConfig.location[0] * pdf_width),
//                    (float) ((1 - sealConfig.location[1]) * pdf_height - image.getHeight()),
//                    (float) (sealConfig.location[0] * pdf_width + image.getWidth()),
//                    (float) ((1 - sealConfig.location[1]) * pdf_height)), sealConfig.page, "" + System.currentTimeMillis());

//            float w = (float) sealConfig.location[2] * pdf_width;
//            float h = (float) sealConfig.location[2] * pdf_width * image.getHeight() / image.getWidth();
//            // x,y是基于pdf左下角为坐标原点
//            // x,y是基于pdf左下角为坐标原点
//            float x = (float) (sealConfig.location[0] * pdf_width);
//            float y = (float) (pdf_height - sealConfig.location[1] * pdf_height - h);
//
//            float llx = x;
//            float lly = y;
//            float urx = x + w;
//            float ury = y + h ;
//            appearance.setVisibleSignature(
//                    new Rectangle(llx, lly, urx, ury)
//                    , sealConfig.page
////                    , "" + System.currentTimeMillis());
//                    , null);
//            stamper.getWriter().setCompressionLevel(5);

            // 摘要算法
            ExternalDigest digest = new BouncyCastleDigest();
//            BouncyCastleProvider provider = new BouncyCastleProvider();
//            Security.addProvider(provider);
//            ExternalSignature externalSignature = new PrivateKeySignature(privateKey, DigestAlgorithms.SHA1, provider.getName());
            ExternalSignature externalSignature = new PrivateKeySignature(privateKey, DigestAlgorithms.SHA1, null);
            MakeSignature.signDetached(appearance, digest, externalSignature, certChain, null, null, null, 0, MakeSignature.CryptoStandard.CMS);

            LocalFileUtil.localBufferWrite(faos.toByteArray(), pdfPath);
        }
        catch(Exception e)
        {
            throw new Exception("签名出错，请稍后重试！", e);
        }
        finally
        {
            if(stamper != null)
            {
                stamper.close();
                stamper = null;
            }
            if(faos != null)
            {
                IOUtils.closeQuietly(faos);
                faos = null;
            }
            if(reader != null)
            {
                reader.close();
                reader = null;
            }
            IOUtils.closeQuietly(fbis);
            fbis = null;
        }
    }


    public static void main(String[] args) {
        try {
            String pdfPath = "C:/Users/Administrator/Desktop/3.pdf";
            String moulagePath = "C:/Users/Administrator/Desktop/seal.png";
            signPDF(pdfPath, moulagePath);
            System.out.println(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
